ICTSC2019 二次予選 問題解説: Welcome to Nginxのページを表示したい!
問題文
あなたはローカルネットワーク上にwebサーバを構築し、IPv6アドレスを使用してwebページに接続できるようにセットアップをしています。
webページへはhttp://nginx.icttoracon.net
でアクセスできるようにしたいです。
nginxのホストには、すでにnginxのパッケージをインストール済みです。
CSR1000Vとnginxのホストには固定でIPv6アドレスを割り当てました。
クライアント(VNC Server)にIPv6アドレスが自動設定されるように、CSR1000VにはSLAACの設定を行いました。
しかし、クライアント(VNC Server)のブラウザからhttp://nginx.icttoracon.net
にアクセスしてもWelcome to Nginxのページを表示させることができません。
このトラブルを解決し、Welcome to Nginxのページを表示させてください。
クライアントが増えても自動でアクセスできるよう、設定変更はCSR1000Vとnginxホストのみとしてください。
DNSサーバはCSR1000Vを使用します。
各ノードにはssh/telnet用にIPv4アドレスが設定されていますので必要に応じて使用してください。
予選終了後に実環境で採点されるので、スコアサーバでの解答は不要です。
接続情報
Host | Protocol | IPv4 address | User/Pass |
---|---|---|---|
CSR1000V | telnet | 192.168.0.1 | admin/admin |
nginx | ssh | 192.168.1.2 | admin/admin |
ゴール
VNCサーバのブラウザからhttp://nginx.icttoracon.net
でWelcome to Nginxのサイトが表示されること
上記のアクセスがIPv6で行われていること
(恒久的な設定でなくても構わない)
問題解説
本問題には3つの原因があります。
順を追って調べてみましょう。
疎通性確認
まずはクライアントマシンからnginxホストまでIPv6で疎通性があるか確認してみます。
簡単な確認ではありますが、トラブル原因のレイヤをある程度限定できます。
ubuntu@ICTSC-VNC:~$ ping fc01::2 -c 4
PING fc01::2(fc01::2) 56 data bytes
64 bytes from fc01::2: icmp_seq=1 ttl=63 time=0.887 ms
64 bytes from fc01::2: icmp_seq=2 ttl=63 time=0.607 ms
64 bytes from fc01::2: icmp_seq=3 ttl=63 time=0.802 ms
64 bytes from fc01::2: icmp_seq=4 ttl=63 time=0.699 ms
--- fc01::2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3040ms
rtt min/avg/max/mdev = 0.607/0.748/0.887/0.110 ms
コマンドの結果から本問題は初期状態でIPv6の疎通性があることが確認できます。
名前解決
名前解決ができるかどうか試してみましょう。
ドメイン名からIPv6アドレスを取得するにはAAAAレコードを参照します。
例としてAAAAレコードを取得するコマンドを以下に示します。
ubuntu@ICTSC-VNC:~$ dig nginx.icttoracon.net AAAA
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> nginx.icttoracon.net AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 40684
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;nginx.icttoracon.net. IN AAAA
;; Query time: 89 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Dec 04 22:46:46 JST 2019
;; MSG SIZE rcvd: 49
ubuntu@ICTSC-VNC:~$
AAAAレコードは取得できていません。
問題文でDNSサーバはCSRとされていますが、クライアントはどこを参照しているのでしょうか。
ubuntu@ICTSC-VNC:~$ cat /etc/resolv.conf | grep -v "^#"
nameserver 127.0.0.53
options edns0
search localdomain
ubuntu@ICTSC-VNC:~$ cat /run/systemd/resolve/resolv.conf | grep -v "^#"
nameserver 133.242.0.3
nameserver 133.242.0.4
search localdomain
ubuntu@ICTSC-VNC:~$
IPv4でDNSサーバを受け取っているようですが、CSRのIPアドレスではありません。
1つ目の原因はDNSサーバ(CSR)が参照できていないことです。
問題文からクライアントの設定変更ではなくルータの設定変更で対応する方針であることがわかります。
クライアントの設定とCSRの設定を確認すると、クライアントのIPv6アドレスはRAを用いた自動設定であることがわかります。
ただしDNSサーバのアドレスが配布されていません。
RAでIPv6アドレスが設定されている場合は、以下の2つの方法でDNSサーバを配布することができます。
- ステートレスDHCPv6
- RAを用いたDNS配布(RFC8106)
例としてRAのみでDNSの配布を行います。
IOS-XEのコマンドリファレンスを参照すると、以下の設定でDNSの配布が行えそうです。
csr1000v#conf t
Enter configuration commands, one per line. End with CNTL/Z.
csr1000v(config)#int gi 1
csr1000v(config-if)#ipv6 nd ra dns server fc00::1
クライアントで確認してみます。
ubuntu@ICTSC-VNC:~$ cat /run/systemd/resolve/resolv.conf | grep -v "^#"
nameserver 133.242.0.3
nameserver 133.242.0.4
nameserver fc00::1
search localdomain
ubuntu@ICTSC-VNC:~$ dig nginx.icttoracon.net AAAA
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> nginx.icttoracon.net AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35863
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;nginx.icttoracon.net. IN AAAA
;; ANSWER SECTION:
nginx.icttoracon.net. 10 IN AAAA fc01::2
;; Query time: 12 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Dec 04 22:51:49 JST 2019
;; MSG SIZE rcvd: 77
ubuntu@ICTSC-VNC:~$
DNSサーバとしてfc00::1
が設定され、AAAAレコードが正しく参照できています。
nginx設定
IPv6の疎通性があり、名前解決も行えているので一旦クライアントの作業を終え、nginxホストを確認してみます。
まずは80ポートの使用状況を確認してみます。
[admin@nginx ~]$ sudo lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1421 root 6u IPv4 9815 0t0 TCP *:http (LISTEN)
nginx 1422 nginx 6u IPv4 9815 0t0 TCP *:http (LISTEN)
typeを見るとIPv4となっており、nginxがIPv6アドレスで待ち受けていないことがわかります。
2つ目の原因はnginxはIPv6アドレスで待ち受けていないことです。
nginxがIPv6アドレスで待ち受けるよう、設定を変更します。
server {
listen 80;
+ listen [::]:80;
server_name localhost;
--- snip ---
[admin@nginx ~]$ sudo nginx -s reload
[admin@nginx ~]$ sudo nginx -s reload
[admin@nginx ~]$ sudo lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1421 root 6u IPv4 9815 0t0 TCP *:http (LISTEN)
nginx 1421 root 10u IPv6 10932 0t0 TCP *:http (LISTEN)
nginx 1540 nginx 6u IPv4 9815 0t0 TCP *:http (LISTEN)
nginx 1540 nginx 10u IPv6 10932 0t0 TCP *:http (LISTEN)
フィルタリング設定
nginxがIPv6で待ち受ける状態となりました。
しかしまだクライアントからアクセスができません。
nginxホストのディストリビューションを確認してみます。
[admin@nginx ~]$ ls /etc | grep release
centos-release
redhat-release
system-release
system-release-cpe
[admin@nginx ~]$ cat /etc/centos-release
CentOS release 6.10 (Final)
[admin@nginx ~]$
CentOS6.10であるため、フィルタリングはiptablesで行っていると予想されます。
iptablesのルールを確認してみましょう。
[admin@nginx ~]$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:http
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
一見すると問題が無いように見えますが、クライアントはWelcome to Nginxのページにアクセスできません。
それもそのはず、iptablesはIPv4のフィルタリング設定だからです。
実は初期状態からIPv4で80ポートは許可されており、クライアントはIPv4を用いてWelcome to Nginxのページを表示させることはできてました。
IPv6のフィルタリングはip6tableで行います。
ip6tableのルールを確認すると、80ポートのアクセスを許可しているルールが無いことがわかります。
[admin@nginx ~]$ sudo ip6tables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all anywhere anywhere state RELATED,ESTABLISHED
ACCEPT ipv6-icmp anywhere anywhere
ACCEPT all anywhere anywhere
ACCEPT udp anywhere fe80::/64 state NEW udp dpt:dhcpv6-client
ACCEPT tcp anywhere anywhere state NEW tcp dpt:ssh
REJECT all anywhere anywhere reject-with icmp6-adm-prohibited
3つ目の原因はIPv6の80ポートが拒否されていることです。
問題文には恒久的な設定ではなくて構わないとしか記載されていないので、80ポートを許可する方法か、プロセスを停止する方法があります。
問題としてはどちらで行ってもいいですが、望ましいのは80ポートを許可する方法です。
ip6tablesで80ポートを許可します。
[admin@nginx ~]$ sudo ip6tables -I INPUT 6 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
[admin@nginx ~]$ sudo ip6tables -I INPUT 6 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
[admin@nginx ~]$ sudo ip6tables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all anywhere anywhere state RELATED,ESTABLISHED
ACCEPT ipv6-icmp anywhere anywhere
ACCEPT all anywhere anywhere
ACCEPT udp anywhere fe80::/64 state NEW udp dpt:dhcpv6-client
ACCEPT tcp anywhere anywhere state NEW tcp dpt:ssh
ACCEPT tcp anywhere anywhere state NEW tcp dpt:http
REJECT all anywhere anywhere reject-with icmp6-adm-prohibited
クライアントでアクセスしてみると、Welcome to Nginxのページが表示されます。